# -*- coding: utf-8 -*-
"""
RBAC权限管理模型

提供基于角色的访问控制(Role-Based Access Control)数据模型：
- User: 用户模型，扩展基础用户信息
- Role: 角色模型，定义用户角色
- Permission: 权限模型，定义系统权限
- Resource: 资源模型，定义受保护的资源
- UserRole: 用户角色关联
- RolePermission: 角色权限关联
- UserPermission: 用户直接权限（可选）
"""

from datetime import datetime
from typing import List, Optional
from sqlalchemy import (
    Boolean, Column, DateTime, ForeignKey, Integer, 
    String, Text, UniqueConstraint, Index, Enum as SQLEnum
)
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship
from sqlalchemy.sql import func
import enum


Base = declarative_base()


# ==================== 枚举定义 ====================

class UserStatus(enum.Enum):
    """用户状态枚举（按照模块文档2.1要求）"""
    ACTIVE = "active"           # 正常：可以正常使用系统
    LOCKED = "locked"          # 锁定：临时禁用，不能登录
    SUSPENDED = "suspended"     # 停用：长期禁用，保留数据
    DELETED = "deleted"        # 删除：逻辑删除，不可恢复


class PermissionAction(enum.Enum):
    """权限操作类型枚举"""
    CREATE = "create"          # 创建
    READ = "read"             # 读取
    UPDATE = "update"         # 更新
    DELETE = "delete"         # 删除
    EXPORT = "export"         # 导出
    IMPORT = "import"         # 导入
    APPROVE = "approve"       # 审批
    MANAGE = "manage"         # 管理


class ResourceType(enum.Enum):
    """资源类型枚举"""
    MODULE = "module"         # 模块
    PAGE = "page"            # 页面
    API = "api"              # API接口
    BUTTON = "button"        # 按钮
    MENU = "menu"            # 菜单
    DATA = "data"            # 数据


# ==================== 核心RBAC模型 ====================

class User(Base):
    """用户模型 - Web版本增强"""
    __tablename__ = "users"
    
    # 基础信息
    id = Column(Integer, primary_key=True, index=True)
    username = Column(String(50), unique=True, nullable=False, index=True, comment="用户名")
    email = Column(String(100), unique=True, nullable=False, index=True, comment="邮箱")
    phone = Column(String(20), comment="手机号")
    
    # 个人信息
    real_name = Column(String(50), nullable=False, comment="真实姓名")
    nickname = Column(String(50), comment="昵称")
    avatar_url = Column(String(255), comment="头像URL")
    
    # 组织信息
    employee_id = Column(String(20), unique=True, index=True, comment="员工编号")
    department = Column(String(50), comment="部门")
    position = Column(String(50), comment="职位")
    manager_id = Column(Integer, ForeignKey("users.id"), comment="直属领导ID")
    
    # 认证信息
    password_hash = Column(String(255), nullable=False, comment="密码哈希")
    password_updated_at = Column(DateTime, comment="密码更新时间")
    login_attempts = Column(Integer, default=0, comment="登录尝试次数")
    locked_until = Column(DateTime, comment="锁定到期时间")
    
    # 状态管理
    status = Column(SQLEnum(UserStatus), nullable=False, default=UserStatus.ACTIVE, comment="用户状态")
    is_superuser = Column(Boolean, default=False, comment="是否超级用户")
    is_active = Column(Boolean, default=True, comment="是否激活")
    
    # 统计信息
    last_login_at = Column(DateTime, comment="最后登录时间")
    last_login_ip = Column(String(45), comment="最后登录IP")
    login_count = Column(Integer, default=0, comment="登录次数")
    
    # 系统字段
    created_at = Column(DateTime, default=func.now(), nullable=False, comment="创建时间")
    updated_at = Column(DateTime, default=func.now(), onupdate=func.now(), nullable=False, comment="更新时间")
    created_by = Column(Integer, ForeignKey("users.id"), comment="创建人")
    updated_by = Column(Integer, ForeignKey("users.id"), comment="更新人")
    
    # 关联关系
    user_roles = relationship("UserRole", back_populates="user", foreign_keys="UserRole.user_id", cascade="all, delete-orphan")
    user_permissions = relationship("UserPermission", back_populates="user", foreign_keys="UserPermission.user_id", cascade="all, delete-orphan")
    created_roles = relationship("Role", foreign_keys="Role.created_by", back_populates="creator")
    
    # 索引
    __table_args__ = (
        Index("idx_user_status_active", "status", "is_active"),
        Index("idx_user_login", "last_login_at"),
        Index("idx_user_department", "department"),
    )


class Role(Base):
    """角色模型"""
    __tablename__ = "roles"
    
    id = Column(Integer, primary_key=True, index=True)
    name = Column(String(50), unique=True, nullable=False, index=True, comment="角色名称")
    code = Column(String(50), unique=True, nullable=False, index=True, comment="角色编码")
    description = Column(Text, comment="角色描述")
    
    # 层级管理
    parent_id = Column(Integer, ForeignKey("roles.id"), comment="父角色ID")
    level = Column(Integer, nullable=False, default=1, comment="角色级别")
    sort_order = Column(Integer, default=0, comment="排序顺序")
    
    # 状态管理
    is_active = Column(Boolean, default=True, comment="是否激活")
    is_system = Column(Boolean, default=False, comment="是否系统角色")
    is_default = Column(Boolean, default=False, comment="是否默认角色")
    
    # 限制管理
    max_users = Column(Integer, comment="最大用户数限制")
    
    # 系统字段
    created_at = Column(DateTime, default=func.now(), nullable=False, comment="创建时间")
    updated_at = Column(DateTime, default=func.now(), onupdate=func.now(), nullable=False, comment="更新时间")
    created_by = Column(Integer, ForeignKey("users.id"), comment="创建人")
    updated_by = Column(Integer, ForeignKey("users.id"), comment="更新人")
    
    # 关联关系
    user_roles = relationship("UserRole", back_populates="role", foreign_keys="UserRole.role_id", cascade="all, delete-orphan")
    role_permissions = relationship("RolePermission", back_populates="role", foreign_keys="RolePermission.role_id", cascade="all, delete-orphan")
    children = relationship("Role", back_populates="parent", remote_side=[parent_id], cascade="all, delete-orphan")
    parent = relationship("Role", remote_side=[id], back_populates="children")
    creator = relationship("User", foreign_keys=[created_by], back_populates="created_roles")
    
    # 索引和约束
    __table_args__ = (
        Index("idx_role_active_system", "is_active", "is_system"),
        Index("idx_role_parent_level", "parent_id", "level"),
    )


class Resource(Base):
    """资源模型 - 定义受保护的系统资源"""
    __tablename__ = "resources"
    
    id = Column(Integer, primary_key=True, index=True)
    name = Column(String(100), nullable=False, comment="资源名称")
    code = Column(String(50), unique=True, nullable=False, index=True, comment="资源编码")
    description = Column(Text, comment="资源描述")
    
    # 资源分类
    type = Column(SQLEnum(ResourceType), nullable=False, comment="资源类型")
    module = Column(String(50), nullable=False, index=True, comment="所属模块")
    
    # 层级结构
    parent_id = Column(Integer, ForeignKey("resources.id"), comment="父资源ID")
    path = Column(String(255), comment="资源路径/URL")
    level = Column(Integer, nullable=False, default=1, comment="资源级别")
    sort_order = Column(Integer, default=0, comment="排序顺序")
    
    # 状态管理
    is_active = Column(Boolean, default=True, comment="是否激活")
    is_system = Column(Boolean, default=False, comment="是否系统资源")
    
    # 系统字段
    created_at = Column(DateTime, default=func.now(), nullable=False, comment="创建时间")
    updated_at = Column(DateTime, default=func.now(), onupdate=func.now(), nullable=False, comment="更新时间")
    created_by = Column(Integer, ForeignKey("users.id"), comment="创建人")
    
    # 关联关系
    permissions = relationship("Permission", back_populates="resource", foreign_keys="Permission.resource_id", cascade="all, delete-orphan")
    children = relationship("Resource", back_populates="parent", remote_side=[parent_id], cascade="all, delete-orphan")
    parent = relationship("Resource", remote_side=[id], back_populates="children")
    
    # 索引
    __table_args__ = (
        Index("idx_resource_type_module", "type", "module"),
        Index("idx_resource_parent_level", "parent_id", "level"),
        UniqueConstraint("code", name="uq_resource_code"),
    )


class Permission(Base):
    """权限模型"""
    __tablename__ = "permissions"
    
    id = Column(Integer, primary_key=True, index=True)
    name = Column(String(100), nullable=False, comment="权限名称")
    code = Column(String(100), unique=True, nullable=False, index=True, comment="权限编码")
    description = Column(Text, comment="权限描述")
    
    # 权限分类
    resource_id = Column(Integer, ForeignKey("resources.id"), nullable=False, comment="关联资源ID")
    action = Column(SQLEnum(PermissionAction), nullable=False, comment="操作类型")
    
    # 权限配置
    conditions = Column(Text, comment="权限条件(JSON格式)")
    data_scope = Column(String(50), comment="数据权限范围")
    
    # 状态管理
    is_active = Column(Boolean, default=True, comment="是否激活")
    is_system = Column(Boolean, default=False, comment="是否系统权限")
    
    # 系统字段
    created_at = Column(DateTime, default=func.now(), nullable=False, comment="创建时间")
    updated_at = Column(DateTime, default=func.now(), onupdate=func.now(), nullable=False, comment="更新时间")
    created_by = Column(Integer, ForeignKey("users.id"), comment="创建人")
    
    # 关联关系
    resource = relationship("Resource", back_populates="permissions")
    role_permissions = relationship("RolePermission", back_populates="permission", foreign_keys="RolePermission.permission_id", cascade="all, delete-orphan")
    user_permissions = relationship("UserPermission", back_populates="permission", foreign_keys="UserPermission.permission_id", cascade="all, delete-orphan")
    
    # 索引和约束
    __table_args__ = (
        Index("idx_permission_resource_action", "resource_id", "action"),
        Index("idx_permission_active", "is_active"),
        UniqueConstraint("resource_id", "action", name="uq_permission_resource_action"),
    )


# ==================== 关联关系表 ====================

class UserRole(Base):
    """用户角色关联表"""
    __tablename__ = "user_roles"
    
    id = Column(Integer, primary_key=True, index=True)
    user_id = Column(Integer, ForeignKey("users.id"), nullable=False, comment="用户ID")
    role_id = Column(Integer, ForeignKey("roles.id"), nullable=False, comment="角色ID")
    
    # 生效管理
    effective_at = Column(DateTime, default=func.now(), comment="生效时间")
    expires_at = Column(DateTime, comment="过期时间")
    is_active = Column(Boolean, default=True, comment="是否激活")
    
    # 系统字段
    created_at = Column(DateTime, default=func.now(), nullable=False, comment="创建时间")
    assigned_by = Column(Integer, ForeignKey("users.id"), comment="分配人")
    
    # 关联关系
    user = relationship("User", back_populates="user_roles", foreign_keys=[user_id])
    role = relationship("Role", back_populates="user_roles", foreign_keys=[role_id])
    
    # 约束和索引
    __table_args__ = (
        UniqueConstraint("user_id", "role_id", name="uq_user_role"),
        Index("idx_user_role_active", "is_active"),
        Index("idx_user_role_effective", "effective_at", "expires_at"),
    )


class RolePermission(Base):
    """角色权限关联表"""
    __tablename__ = "role_permissions"
    
    id = Column(Integer, primary_key=True, index=True)
    role_id = Column(Integer, ForeignKey("roles.id"), nullable=False, comment="角色ID")
    permission_id = Column(Integer, ForeignKey("permissions.id"), nullable=False, comment="权限ID")
    
    # 权限配置
    is_granted = Column(Boolean, default=True, comment="是否授予(支持拒绝权限)")
    data_scope = Column(String(50), comment="数据权限范围覆盖")
    conditions = Column(Text, comment="额外权限条件")
    
    # 系统字段
    created_at = Column(DateTime, default=func.now(), nullable=False, comment="创建时间")
    assigned_by = Column(Integer, ForeignKey("users.id"), comment="分配人")
    
    # 关联关系
    role = relationship("Role", back_populates="role_permissions", foreign_keys=[role_id])
    permission = relationship("Permission", back_populates="role_permissions", foreign_keys=[permission_id])
    
    # 约束和索引
    __table_args__ = (
        UniqueConstraint("role_id", "permission_id", name="uq_role_permission"),
        Index("idx_role_permission_granted", "is_granted"),
    )


class UserPermission(Base):
    """用户直接权限关联表 - 支持用户特殊权限"""
    __tablename__ = "user_permissions"
    
    id = Column(Integer, primary_key=True, index=True)
    user_id = Column(Integer, ForeignKey("users.id"), nullable=False, comment="用户ID")
    permission_id = Column(Integer, ForeignKey("permissions.id"), nullable=False, comment="权限ID")
    
    # 权限配置
    is_granted = Column(Boolean, default=True, comment="是否授予")
    data_scope = Column(String(50), comment="数据权限范围")
    conditions = Column(Text, comment="权限条件")
    
    # 生效管理
    effective_at = Column(DateTime, default=func.now(), comment="生效时间")
    expires_at = Column(DateTime, comment="过期时间")
    is_active = Column(Boolean, default=True, comment="是否激活")
    
    # 系统字段
    created_at = Column(DateTime, default=func.now(), nullable=False, comment="创建时间")
    assigned_by = Column(Integer, ForeignKey("users.id"), comment="分配人")
    reason = Column(Text, comment="分配原因")
    
    # 关联关系
    user = relationship("User", back_populates="user_permissions", foreign_keys=[user_id])
    permission = relationship("Permission", back_populates="user_permissions", foreign_keys=[permission_id])
    
    # 约束和索引
    __table_args__ = (
        UniqueConstraint("user_id", "permission_id", name="uq_user_permission"),
        Index("idx_user_permission_active", "is_active"),
        Index("idx_user_permission_effective", "effective_at", "expires_at"),
    )


# ==================== 权限日志表 ====================

class PermissionLog(Base):
    """权限操作日志表"""
    __tablename__ = "permission_logs"
    
    id = Column(Integer, primary_key=True, index=True)
    
    # 操作信息
    operation_type = Column(String(20), nullable=False, comment="操作类型")
    target_type = Column(String(20), nullable=False, comment="目标类型")
    target_id = Column(Integer, nullable=False, comment="目标ID")
    
    # 操作内容
    before_data = Column(Text, comment="操作前数据")
    after_data = Column(Text, comment="操作后数据")
    operation_desc = Column(Text, comment="操作描述")
    
    # 操作人信息
    operator_id = Column(Integer, ForeignKey("users.id"), comment="操作人ID")
    operator_ip = Column(String(45), comment="操作IP")
    
    # 系统字段
    created_at = Column(DateTime, default=func.now(), nullable=False, comment="创建时间")
    
    # 索引
    __table_args__ = (
        Index("idx_permission_log_type_target", "operation_type", "target_type"),
        Index("idx_permission_log_operator", "operator_id"),
        Index("idx_permission_log_created", "created_at"),
    )